package ALG;/*

 */

import com.sun.xml.internal.ws.runtime.config.TubelineFeatureReader;

import java.util.*;

/**
 * @ClassName Solution
 * @Author Final
 * @Project DataStructures
 */
public class Solution {
    public static void main(String[] args) {

        // int arr[] ={2,7,11,15};
        // int arr1[] ={1,3,7,11,15};
        // int target=9;

        //int[] ints = twoSum(arr, target);

        // int[] ints = nextGreaterElement(arr, arr1);
        // for (int i = 0; i < ints.length; i++) {
        //     System.out.println(ints[i]);
        // }

        // int i = lengthOfLongestSubstring2("11234fava");
        // System.out.println(i);

        // String result = longestPalindrome("sbsasssa");
        String results = longestPalindrome1("sbsasssa");
        System.out.println("*************result****************");
        // System.out.println(result);
        System.out.println(results);
    }

    /**
     * 两数之和
     * @param nums
     * @param target
     * @return
     */
    private static  int[] twoSum(int[] nums, int target){
        Map<Integer, Integer> map = new HashMap<>();
        for (int i = 0; i < nums.length; i++){
            if (map.containsKey(target - nums[i])){
                return new int[] {map.get(target - nums[i]),i};
            }
            map.put(nums[i], i);
        }
        return null;
    }

    public static int[] nextGreaterElement(int[] nums1, int[] nums2) {

        int[] ints = new int[nums1.length];
        for (int i = 0; i < nums1.length; i++) {
            for (int j = 0; j < nums2.length; j++) {
                if (nums1[i]+1<nums2[j]){
                    ints[i]=nums2[j];
                    break;
                }else
                {
                    ints[i]=-1;
                }
            }
        }
        return ints;
    }

    /**
     * 无重复字符的最长子串
     * @param s
     * @return
     */
    public static int lengthOfLongestSubstring1(String s) {

        int i = 0;
        int flag = 0;
        int length = 0;
        int result = 0;
        while (i < s.length()) {
            int pos = s.indexOf(s.charAt(i),flag);
            if (pos < i) {
                if (length > result) {
                    result = length;
                }
                if (result >= s.length() - pos - 1) {
                    return result;
                }
                length = i - pos - 1;
                flag = pos + 1;
            }
            length++;
            i++;
        }
        return length;

    }

    public static int lengthOfLongestSubstring(String s) {

        HashMap<Character, Integer> map = new HashMap<>();
        int max = 0, start = 0;
        for (int end = 0; end < s.length(); end++) {
            char ch = s.charAt(end);
            if (map.containsKey(ch)){
                start = Math.max(map.get(ch)+1,start);
            }

            max = Math.max(max,end - start + 1);
            map.put(ch,end);
        }
        return max;
    }

    public static int lengthOfLongestSubstring2(String s) {

        // 记录字符上一次出现的位置
        int[] last = new int[128];
        for(int i = 0; i < 128; i++) {
            last[i] = -1;
        }
        int n = s.length();

        int res = 0; //长度
        int start = 0; // 窗口开始位置
        for(int i = 0; i < n; i++) {
            int index = s.charAt(i);
            System.out.println("index---->"+index);

            System.out.println("last[index]+1------->"+last[index]);
            System.out.println("start前------>"+start);
            start = Math.max(start, last[index] + 1);
            System.out.println("start后------>"+start);
            res   = Math.max(res, i - start + 1);
            System.out.println("res--------->"+res);
            last[index] = i;
            System.out.println(last[index]);
            System.out.println("************************************************************");
        }

        return res;
    }

    /**
     *
     * 最长回文数
     * @param s
     * @return
     */
    public static String longestPalindrome1(String s){

        int len = s.length();
        if (len < 2) {
            return s;
        }


        //同于记录当前最长的回文长度和起始位置
        int maxLen = 1;//初始化从1开始，原因单个字符一定是回文子串
        int begin = 0;

        // dp[i][j] 表示 s[i..j] 是否是回文串
        boolean[][] dp = new boolean[len][len];

        // 初始化：所有长度为 1 的子串都是回文串
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        char[] charArray = s.toCharArray();

        // 动态规划：递推开始dp[i][j]，注意顺序影响记录最长的回文串长度

        // 先枚举子串长度
        for (int L = 2; L <= len; L++) {

            // 针对每个长度的回文子串,枚举左边界i，注意：i的上限可以用右边界j来限制(j<len)
            /**
             i:对应回文串的左边界序号
             j:对应回文串的右边界序号
             */
            for (int i = 0; i < len; i++) {

                // 由 L 和 i 可以确定右边界，即 j - i + 1 = L 当前的回文串长度得：
                int j = L + i - 1;

                // 如果右边界越界，就可以退出当前循环（i的上限可以用右边界j来限制(j<len)）
                if (j >= len) {
                    break;
                }


                //开始判断dp[i][j]的值
                if (charArray[i] != charArray[j]) {
                    //当前最外面的两个字符不相等
                    dp[i][j] = false;

                } else {
                    //首要是当前最外面的两个字符相等
                    if (j - i < 3) {
                        //针对i和j为相邻的元素（把这种情况放在里面，出于“录当前最长的回文长度”！！！！）
                        dp[i][j] = true;

                    } else {
                        //针对i和j不是相邻的元素（“动态递归判断”，短的影响长的，往外扩散）
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }



                //此时记录当前最长的回文长度和起始位置
                //dp生成的顺序决定了是否遍历了所有的情况
                // 只要 dp[i][L] == true 成立，就表示子串 s[i..L] 是回文
                if (dp[i][j] && j - i + 1 > maxLen) {
                    maxLen = j - i + 1;
                    begin = i;
                }

            }
        }

        //当前全部判断完所有的情况（更新了最优的begin和maxLen）
        return s.substring(begin, begin + maxLen);
    }


}
